package com.yhy.wxzn.wcs.device.netty.decoder;

import com.yhy.wxzn.wcs.device.netty.bean.SiemensMessage;
import com.yhy.wxzn.wcs.device.netty.commons.Utility;
import com.yhy.wxzn.wcs.device.netty.enumerate.CommandType;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.internal.StringUtil;

import java.util.List;

public class SiemensDecoder extends ByteToMessageDecoder {
    public SiemensDecoder() {
    }

    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int length = in.readableBytes();
        if (length >= 12) {
            short header = in.readShort();
            if (header == 768) {
                short messageLength = in.readShort();
                if (messageLength == length) {
                    int type = Utility.byteToInt(in.getByte(11));
                    SiemensMessage msg = new SiemensMessage();
                    switch(type) {
                        case 4:
                            msg.setType(CommandType.Head2);
                            break;
                        case 192:
                            msg.setType(CommandType.Head1);
                            break;
                        default:
                            this.readOrWrite(in, msg);
                    }

                    out.add(msg);
                }
            }

            in.clear();
        }
    }

    private void readOrWrite(ByteBuf in, SiemensMessage msg) {
        String errorMsg = "";
        int type = 0;
        int code = 0;
        in.skipBytes(12);
        int endLength = Utility.byteToInt(in.readByte());
        in.skipBytes(2);
        int l = in.readableBytes();
        if (l > 0) {
            type = Utility.byteToInt(in.readByte());
            in.skipBytes(1);
            code = Utility.byteToInt(in.readByte());
        }

        switch(type) {
            case 4:
                msg.setType(CommandType.Read);
                if (code == 255) {
                    int bType = Utility.byteToInt(in.readByte());
                    int dataLength = in.readShort();
                    if (bType == 4) {
                        dataLength /= 8;
                    }

                    if (in.readerIndex() + dataLength > in.writerIndex()) {
                        errorMsg = "读取PLC数据长度错误！";
                    } else {
                        ByteBuf value = in.readBytes(dataLength);
                        msg.setDataValue(value);
                        errorMsg = null;
                    }
                } else {
                    errorMsg = "读取数据失败！";
                }
                break;
            case 5:
                msg.setType(CommandType.Write);
                if (code == 255) {
                    errorMsg = null;
                } else {
                    errorMsg = "写入数据失败！";
                }
                break;
            default:
                msg.setType(CommandType.Error);
                errorMsg = "请检查TIA组态页面中是否勾选“允许来自远程对象的Put/Get通信访问”！或者检查是否去掉DB块属性的“优化的块访问”的勾！";
        }

        msg.setSuccess(StringUtil.isNullOrEmpty(errorMsg));
        msg.setMessage(errorMsg);
    }
}
